#pragma once
#include <vector>
#include <windows.h>
#include <sstream>
#include "SingleClass.h"
#include <string>
#include <iostream>
#include <mutex>
#include <conio.h>
using namespace std;

const int width = 24;
const int height = 24;

struct point {
    int x;
    int y;

    point(int m, int n) {
        x = m;
        y = n;
    }

    /*point(point& new_point) {
        x = new_point.x;
        y = new_point.y;
    }*/
};

class background :public Singleton<background> {
    friend Singleton<background>;
private:
    //打印板
    vector<vector<int>> _b;
    //蛇身长度，就是得分+1。
    unsigned int _length;
    unsigned int _empty;
    //蛇是否存活
    bool _isalive;

    vector<point> _s;

    //方向上下左右
    enum Direction { UP, DOWN, LEFT, RIGHT };
    Direction _direction;

    //食物位置
    int _x;
    int _y;

    mutex _mtx;
    


public:
    background() :_b(width, vector<int>(height))
        , _isalive(true), _length(1),_direction(UP),_empty(484) {
        //生成1-23的随机整数
        _x = (rand() % 22) + 1;
        _y = (rand() % 22) + 1;
        _s.push_back(point(width / 2, height / 2));
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                if (i == 0 || i == (width - 1) || j == 0 || j == (height - 1)) {
                    //初始化边框
                    _b[i][j] = 1;
                }
                else if (i == width / 2 && j == height / 2) {
                    //初始蛇
                    _b[i][j] = 2;
                }
                else if (i == _x && j == _y) {
                    //初始化食物
                    _b[i][j] = 3;
                }
            }
        }
    }

    //回到输出初始位置
    void MoveCursortToTopLeft() {
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        COORD coord = { 0, 0 };
        SetConsoleCursorPosition(hConsole, coord);
    }

    //打印函数(优化版)
    void PrintOnce() {
        while (_isalive) {
            auto frameStart = std::chrono::steady_clock::now();

            // 生成当前帧的缓冲区
            std::stringstream buffer;
            {
                std::lock_guard<std::mutex> lock(_mtx);
                for (int i = 0; i < width; i++) {
                    for (int j = 0; j < height; j++) {
                        char c = ' ';
                        switch (_b[i][j]) {
                        case 1: c = '#'; break;
                        case 2: c = 'o'; break;
                        case 3: c = '$'; break;
                        }
                        buffer << c;
                    }
                    buffer << "\n";
                }
                buffer << "\n\n得分：" << _length - 1 << std::endl;
            }

            // 仅更新变化部分（可选优化，此处简化为全量更新）
            MoveCursortToTopLeft();  // 光标回到左上角，覆盖而非清屏
            std::cout << buffer.str() << std::flush;  // 一次性输出整帧

            // 控制帧率（例如60 FPS）
            auto frameTime = std::chrono::steady_clock::now() - frameStart;
            auto targetDelay = std::chrono::milliseconds(1000 / 60);  // 60 FPS
            if (frameTime < targetDelay) {
                std::this_thread::sleep_for(targetDelay - frameTime);
            }
        }
    }

    //检测按键
    void keyboard() {
        while (_isalive) {
            if (_kbhit()) {
                int ch = _getch();
                ch = toupper(ch);  // 统一转换为大写
                switch (ch) {
                case 'W':
                    if (_direction != DOWN) {
                        _direction = UP;
                    }
                    break;
                case 'S':
                    if (_direction != UP) {
                        _direction = DOWN;
                    }
                    break;
                case 'A':
                    if (_direction != RIGHT) {
                        _direction = LEFT;
                    }
                    break;
                case 'D':
                    if (_direction != LEFT)
                        _direction = RIGHT;
                    break;
                }
            }
        }
    }

    //更新蛇身数组
    void updatasnake() {
        for (int i=_s.size()-1; i>0 ; i--) {
            _s[i] = _s[i-1];
        }
    }

    void Move() {
        lock_guard<mutex> lock(_mtx);
        //先保存蛇尾位置
        int tempx = _s[_length - 1].x;
        int tempy = _s[_length - 1].y;
        switch (_direction) {
            case UP:    // 使用枚举值
                updatasnake();
                _s.front().x--;
                break;
            case DOWN:
                updatasnake();
                _s.front().x++;
                break;
            case LEFT:
                updatasnake();
                _s.front().y--;
                break;
            case RIGHT:
                updatasnake();
                _s.front().y++;
                break;
        }
        //吃到食物
        if (_b[_s.front().x][_s.front().y] == 3) {
            _length++;
            _empty--;
            //身子往后长一格
            _s.push_back(point(tempx,tempy));
            //随机生成食物（不能生成在蛇身上）
            do {
                //当空白位置太少了很难随机到，直接指定
                if (_empty < 10) {
                    find_if(_b.begin(), _b.end(), [&](vector<int>& row) {
                        auto ij = find_if(row.begin(), row.end(), [&](int& x) {
                            return x == 0;//找到空位
                            });
                        *ij = 3;
                        return ij != row.end();
                        });
                }
                _x = (rand() % 22) + 1;
                _y = (rand() % 22) + 1;
            } while (find_if(_s.begin(), _s.end(), [&](const point& body) {
                return body.x == _x && body.y == _y;
                })!=_s.end()); // 若生成在蛇身上，重新生成
            _b[_x][_y] = 3;
        }
        //没吃到
        else {
            //蛇尾置零
            _b[tempx][tempy] = 0;

        }
    }

    //刷新函数
    void updata() {
        lock_guard<mutex> lock(_mtx);
        //咬到自己或者撞墙
        if (_s.front().x == 0 || _s.front().y == 0 ||
            _s.front().x == width-1 || _s.front().y == height-1||
            _b[_s.front().x][_s.front().y]==2) {
            _isalive = false;
            return;
        }
        for (int i = 0; i < _s.size(); i++) {
            //所有身子占格设为2
             _b[_s[i].x][_s[i].y] = 2;
        }
    }

    bool Getislive() const{
        return _isalive;
    }
};